﻿using JESAI.Application.Abstractions.Admin;
using JESAI.Application.Abstractions.Admin.Dtos.User;
using JESAI.Application.Abstractions.Dtos;
using JESAI.AutoMapper.ObjectMapping;
using JESAI.Core.Attributes;
using JESAI.Core.Extensions;
using JESAI.Core.Randoms;
using JESAI.Core.Util.Helpers;
using JESAI.Platform.Domain.Admin.Entities;
using JESAI.Platform.Domain.Admin.Repositories;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JESAI.Application.Service.Admin
{
    [AppService]
    public class UserService : IUserService
    {
        private readonly IUserRepository _userRepository;
        private readonly IRoleRepository _roleRepository;
        private readonly IUserRoleRepository _userRoleRepository;
        public UserService(IUserRepository userRepository, IRoleRepository roleRepository, IUserRoleRepository userRoleRepository)
        {
            _userRepository = userRepository;
            _roleRepository = roleRepository;
            _userRoleRepository = userRoleRepository;
        }

        public void DeleteUser(long id)
        {
            _userRepository._DbQueryable.Context.Ado.BeginTran();
            try
            {
                _userRepository.DeleteById(id);
                //同时删除用户角色关系
                _userRoleRepository.Delete(p => p.Uid == id);
                _userRepository._DbQueryable.Context.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                _userRepository._DbQueryable.Context.Ado.RollbackTran();
                throw new Exception("事务执行失败", ex);
            }
        }

        public void DeleteUsers(long[] ids)
        {
            _userRepository._DbQueryable.Context.Ado.BeginTran();
            try
            {
                _userRepository.DeleteByIds(ids as dynamic);
                //同时删除用户角色关系
                _userRoleRepository.Delete(p => ids.Contains(p.Uid));
                _userRepository._DbQueryable.Context.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                _userRepository._DbQueryable.Context.Ado.RollbackTran();
                throw new Exception("事务执行失败", ex);
            }
        }

        public BaseOutput<List<QueryUserDto>> QueryAllUsers(QueryAllUsersInput input)
        {
            var userList = new List<QueryUserDto>();
            if (input.RoleId > 0)
            {
                userList = _userRepository._DbQueryable.Context.Queryable<UserModel, UserRoleModel>((u, urole) => new object[] { JoinType.Inner, u.Id == urole.Uid })
                                          .Where((u, urole) => urole.RoleId == input.RoleId)
                                          .WhereIF(input.State > -1, (u, urole) => u.State == input.State)
                                          .WhereIF(!input.RealName.IsEmpty(), (u, urole) => u.RealName == input.RealName)
                                          .WhereIF(!input.UserName.IsEmpty(), (u, urole) => u.UserName == input.UserName)
                                          .WhereIF(!input.Mobile.IsEmpty(), (u, urole) => u.Mobile == input.Mobile)
                                          .Select((u, urole) => new QueryUserDto { Id = u.Id, Mobile = u.Mobile, RealName = u.RealName, State = u.State, UpdateTime = u.UpdateTime, UserName = u.UserName, Email = u.Email })
                                          .ToList();
            }
            else if (!input.PlatformKey.IsEmpty())
            {
                // 项目角色Id数组
                var roleIdList = _roleRepository._DbQueryable.Where(it => it.PlatformKey == input.PlatformKey && it.IsDel == false).Select(it => it.Id).ToList();
                // 查询
                userList = _userRepository._DbQueryable.Context.Queryable<UserModel, UserRoleModel>((u, urole) => new object[] { JoinType.Inner, u.Id == urole.Uid })
                                          .Where((u, urole) => roleIdList.Contains(urole.RoleId))
                                          .WhereIF(input.State > -1, (u, urole) => u.State == input.State)
                                          .WhereIF(!input.RealName.IsEmpty(), (u, urole) => u.RealName == input.RealName)
                                          .WhereIF(!input.UserName.IsEmpty(), (u, urole) => u.UserName == input.UserName)
                                          .WhereIF(!input.Mobile.IsEmpty(), (u, urole) => u.Mobile == input.Mobile)
                                          .GroupBy((u, urole) => u.Id)
                                          .Select((u, urole) => new QueryUserDto { Id = u.Id, Mobile = u.Mobile, RealName = u.RealName, State = u.State, UpdateTime = u.UpdateTime, UserName = u.UserName, Email = u.Email })
                                          .ToList();
            }
            else
            {
                userList = _userRepository._DbQueryable
                                          .WhereIF(input.State > -1, f => f.State == input.State)
                                          .WhereIF(!input.RealName.IsEmpty(), f => f.RealName == input.RealName)
                                          .WhereIF(!input.UserName.IsEmpty(), f => f.UserName == input.UserName)
                                          .WhereIF(!input.Mobile.IsEmpty(), f => f.Mobile == input.Mobile)
                                          .Select(u => new QueryUserDto { Id = u.Id, Mobile = u.Mobile, RealName = u.RealName, State = u.State, UpdateTime = u.UpdateTime, UserName = u.UserName, Email = u.Email })
                                          .ToList();
            }

            return new BaseOutput<List<QueryUserDto>> { Data = userList };
        }

        public List<QueryUserDto> QueryPageUsers()
        {
            var userModels = _userRepository.AsQueryable().ToList();

            return userModels.MapTo<List<QueryUserDto>>();
        }

        public BasePageOutput<List<QueryUserDto>> QueryPageUsers(QueryUsersInput input)
        {
            var userList = new List<QueryUserDto>();
            var totalNumber = 0;
            if (input.RoleId > 0)
            {
                userList = _userRepository._DbQueryable.Context.Queryable<UserModel, UserRoleModel>((u, urole) => new object[] { JoinType.Inner, u.Id == urole.Uid })
                                          .Where((u, urole) => urole.RoleId == input.RoleId)
                                          .WhereIF(input.State > -1, (u, urole) => u.State == input.State)
                                          .WhereIF(!input.DepartmentId.IsEmpty(), (u, urole) => u.DepartmentId == input.DepartmentId)
                                          .WhereIF(!input.RealName.IsEmpty(), (u, urole) => u.RealName == input.RealName)
                                          .WhereIF(!input.UserName.IsEmpty(), (u, urole) => u.UserName == input.UserName)
                                          .WhereIF(!input.Mobile.IsEmpty(), (u, urole) => u.Mobile == input.Mobile)
                                          .Select((u, urole) => new QueryUserDto { Id = u.Id, Mobile = u.Mobile, RealName = u.RealName, State = u.State, UpdateTime = u.UpdateTime, UserName = u.UserName, Email = u.Email })
                                          .ToPageList(input.PageIndex, input.PageSize, ref totalNumber);
            }
            else if (!input.PlatformKey.IsEmpty())
            {
                // 项目角色Id数组
                var roleIdList = _roleRepository._DbQueryable.Where(it => it.PlatformKey == input.PlatformKey && it.IsDel == false).Select(it => it.Id).ToList();
                // 查询
                userList = _userRepository._DbQueryable.Context.Queryable<UserModel, UserRoleModel>((u, urole) => new object[] { JoinType.Inner, u.Id == urole.Uid })
                                          .Where((u, urole) => roleIdList.Contains(urole.RoleId))
                                          .WhereIF(input.State > -1, (u, urole) => u.State == input.State)
                                            .WhereIF(!input.DepartmentId.IsEmpty(), (u, urole) => u.DepartmentId == input.DepartmentId)
                                          .WhereIF(!input.RealName.IsEmpty(), (u, urole) => u.RealName == input.RealName)
                                          .WhereIF(!input.UserName.IsEmpty(), (u, urole) => u.UserName == input.UserName)
                                          .WhereIF(!input.Mobile.IsEmpty(), (u, urole) => u.Mobile == input.Mobile)
                                          .GroupBy((u, urole) => u.Id)
                                          .Select((u, urole) => new QueryUserDto { Id = u.Id, Mobile = u.Mobile, RealName = u.RealName, State = u.State, UpdateTime = u.UpdateTime, UserName = u.UserName, Email = u.Email })
                                          .ToPageList(input.PageIndex, input.PageSize, ref totalNumber);
            }
            else
            {
                userList = _userRepository._DbQueryable
                                          .WhereIF(input.State > -1, f => f.State == input.State)
                                            .WhereIF(!input.DepartmentId.IsEmpty(), f => f.DepartmentId == input.DepartmentId)
                                          .WhereIF(!input.RealName.IsEmpty(), f => f.RealName == input.RealName)
                                          .WhereIF(!input.UserName.IsEmpty(), f => f.UserName == input.UserName)
                                          .WhereIF(!input.Mobile.IsEmpty(), f => f.Mobile == input.Mobile)
                                          .Select(u => new QueryUserDto { Id = u.Id, Mobile = u.Mobile, RealName = u.RealName, State = u.State, UpdateTime = u.UpdateTime, UserName = u.UserName, Email = u.Email })
                                          .ToPageList(input.PageIndex, input.PageSize, ref totalNumber);
            }
            // 当前所有用户id
            var userIdList = userList.Select(it => it.Id);
            // 查询用户及对应角色列表
            var userRoleList = _roleRepository._DbQueryable.Context.Queryable<RoleModel, UserRoleModel>((role, urole) => new object[] { JoinType.Inner, role.Id == urole.RoleId })
                                              .Where((role, urole) => userIdList.Contains(urole.Uid))
                                              .Select((role, urole) => new RoleListDto { Id = role.Id, Name = role.Name, ProjectName = role.PlatformKey, Uid = urole.Uid })
                                              .ToList();
            // 组合用户对应角色
            userList.ForEach(m =>
            {
                m.RoleList = userRoleList.Where(it => it.Uid == m.Id).ToList();
            });
            return new BasePageOutput<List<QueryUserDto>> { Data = userList, CurrentPage = input.PageIndex, Total = totalNumber };
        }

        public List<QueryUserDto> QueryUsers()
        {
            var userModels = _userRepository.AsQueryable().ToList();

            return userModels.MapTo<List<QueryUserDto>>();
        }


        public void UpdayeOrInsert(SetUserInput input)
        {
            try
            {
                _userRepository._DbQueryable.Context.Ado.BeginTran();

                var model = input.MapTo<UserModel>();
                if (model.Id > 0)
                {
                    model.UpdateTime = DateTime.Now;
                    if (!model.Password.IsEmpty())
                    {
                        model.Salt = Randoms.CreateRandomValue(8, false);
                        model.Password = Encrypt.SHA256(model.Password + model.Salt);
                        // 基础字段不容许更新
                        _userRepository.AsUpdateable(model)
                                       .IgnoreColumns(it => new { it.UserName, it.Mobile, it.CreateTime })
                                       .ExecuteCommand();
                    }
                    else
                    {
                        // 基础字段不容许更新
                        _userRepository.AsUpdateable(model)
                                       .IgnoreColumns(it => new { it.UserName, it.Password, it.Salt, it.Mobile, it.CreateTime })
                                       .ExecuteCommand();
                    }
                }
                else
                {
                    model.CreateTime = DateTime.Now;
                    model.UpdateTime = DateTime.Now;
                    model.Salt = Randoms.CreateRandomValue(8, false);
                    model.Password = Encrypt.SHA256(model.Password + model.Salt);
                    model.Id = Convert.ToInt64($"{Time.GetUnixTimestamp()}{Randoms.CreateRandomValue(3, true)}");
                    _userRepository.AsInsertable(model).ExecuteCommand();
                }
                // 用户角色操作
                var userRoleList = new List<UserRoleModel>();
                foreach (var id in input.RoleIdList)
                {
                    // 防止重复数据
                    if (!userRoleList.Exists(it => it.RoleId == id))
                    {
                        userRoleList.Add(new UserRoleModel
                        {
                            Uid = model.Id,
                            RoleId = id
                        });
                    }
                }
                // 删除用户当前角色
                _userRoleRepository.AsDeleteable().Where(f => f.Uid == model.Id).ExecuteCommand();
                // 添加用户角色
                if (userRoleList.Count > 0)
                    _userRoleRepository.AsInsertable(userRoleList).ExecuteCommand();

                _userRepository._DbQueryable.Context.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                _userRepository._DbQueryable.Context.Ado.RollbackTran();
                throw new Exception("事务执行失败", ex);
            }
        }
    }
}
